import CesiumUtil from "@/utils/cesiumUtil";
export default class EditModel {
  constructor(option) {
    this.Vm = option.Vm;
    this.viewer = option.viewer;
    this.handlersTooltip = null;
    this.handlers = null;
    this.tooltip = null;
    this.tooltipText = '';
    this.util = new CesiumUtil(this.viewer);
    this.createTooltip();

    this.editModel = null;
    this.axisModel = null;
  }

  pickModel(option) {
    if (this.viewer && option) {
      this.m_start('单击选中');
      const { callback } = option;
      let position = null;
      this.handlersTooltip = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);

      // 左键单击
      this.handlersTooltip.setInputAction((movement) => {
        const primitive = this.viewer.scene.pick(movement.position);
        if (primitive && primitive.primitive.attribute && primitive.primitive.attribute.serverType && (primitive.primitive.attribute.serverType == 'glb' || primitive.primitive.attribute.serverType == 'gltf')) {
          let cartesian = this.util.getCatesian3FromPX(movement.position);
          if (cartesian && cartesian.x) {
            position = cartesian;
          }
          if (typeof callback === 'function') {
            callback(primitive.primitive);
            this.activeEdit(primitive.primitive);
          }
          this.m_end();
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

      // 移动
      this.handlersTooltip.setInputAction((movement) => {
        this.moveTooltip(movement);
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    }
  }

  // 加载坐标轴模型
  activeEdit(model) {
    this.cancelEdit();
    this.editModel = model;
    let axisModel = this.viewer.scene.primitives.add(Cesium.Model.fromGltf({
      name: 'axis',
      id: 'axis',
      url: 'data/model/axis.gltf',
      modelMatrix: new Cesium.Matrix4(),
      colorBlendMode: Cesium.ColorBlendMode.HIGHLIGHT
    }));

    axisModel.readyPromise.then((axisModel) => {
      axisModel.activeAnimations.addAll({
        loop: Cesium.ModelAnimationLoop.REPEAT
      });
      this.axisModel = axisModel;
      this.updateAxisMatrix();
    });
    this.initModelEditEvent();
  }

  // 删除坐标轴模型
  cancelEdit() {
    this.handlers && this.handlers.destroy();
    this.handlers = null;
    this.axisModel && this.viewer.scene.primitives.remove(this.axisModel);
    this.axisModel = null;
  }

  // 更新坐标轴模型的位置
  updateAxisMatrix() {
    let scale = this.editModel.boundingSphere.radius / this.editModel.attribute.scale;
    this.axisModel.modelMatrix = Cesium.Matrix4.multiplyByUniformScale(this.editModel.modelMatrix, scale, new Cesium.Matrix4());
  }

  // 坐标轴模型事件
  initModelEditEvent() {
    !this.handlers && (this.handlers = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas));
    let axisType = '', showAxis = false;

    // 左键按下
    this.handlers.setInputAction((event) => {
      var pickedObject = this.viewer.scene.pick(event.position);
      if (Cesium.defined(pickedObject) && pickedObject.id === this.axisModel.id) {
        axisType = pickedObject.detail.node._name;
        showAxis = true;
      }
    }, Cesium.ScreenSpaceEventType.LEFT_DOWN);

    // 左键弹起
    this.handlers.setInputAction((event) => {
      showAxis = false;
      this.cameraControl(true);
    }, Cesium.ScreenSpaceEventType.LEFT_UP);

    // 鼠标拖动
    this.handlers.setInputAction((event) => {
      let primitive = this.viewer.scene.pick(event.startPosition);
      if (!primitive || !primitive.id || primitive.id != 'axis') return;

      var startCartesian3 = this.viewer.scene.pickPosition(event.startPosition);
      var endCartesian3 = this.viewer.scene.pickPosition(event.endPosition);

      if (showAxis && startCartesian3 && endCartesian3) {
        this.cameraControl(false); // 禁止球转动和拖动
        switch (axisType) {
          case 'XArrow_1':
            axisMove(startCartesian3, endCartesian3, Cesium.Cartesian3.UNIT_X, 'x', 'z', axisType);
            break;
          case 'YArrow_1':
            axisMove(startCartesian3, endCartesian3, Cesium.Cartesian3.UNIT_Z, 'y', 'z', axisType);
            break;
          case 'ZArrow_1':
            axisMove(startCartesian3, endCartesian3, Cesium.Cartesian3.UNIT_Y, 'x', 'y', axisType);
            break;

          case 'XAxis_1':
            axisRotate(startCartesian3, endCartesian3, Cesium.Cartesian3.UNIT_Y, 'z', 'x');
            break;
          case 'YAxis_1':
            axisRotate(startCartesian3, endCartesian3, Cesium.Cartesian3.UNIT_X, 'y', 'z');
            break;
          case 'ZAxis_1':
            axisRotate(startCartesian3, endCartesian3, Cesium.Cartesian3.UNIT_Z, 'x', 'y');
            break;
        }
        this.updateToView();
      }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

    //平移模型 处理
    const axisMove = (startCartesian3, endCartesian3, surface, zeroAxis1, zeroAxis2, axisType) => {
      let modelMatrix = this.editModel.modelMatrix;
      Cesium.Matrix4.multiplyByUniformScale(modelMatrix, 1 / this.editModel.attribute.scale, modelMatrix);
      let point = axisTransForm(modelMatrix, startCartesian3, endCartesian3, surface);
      let sub = Cesium.Cartesian3.subtract(point.end, point.start, new Cesium.Cartesian3()); // 两点差值
      sub[zeroAxis1] = 0;
      sub[zeroAxis2] = 0;

      const translation = Cesium.Matrix4.fromTranslation(sub);
      Cesium.Matrix4.multiply(modelMatrix, translation, modelMatrix);
      Cesium.Matrix4.multiplyByUniformScale(modelMatrix, this.editModel.attribute.scale, modelMatrix);

      //更新 坐标轴模型 
      this.updateAxisMatrix();
    };

    //旋转模型 处理
    const axisRotate = (startCartesian3, endCartesian3, surface, tant1, tant2) => {
      let modelMatrix = this.editModel.modelMatrix;
      let point = axisTransForm(modelMatrix, startCartesian3, endCartesian3, surface);

      // 两点角度
      let tant = (point.start[tant1] * point.end[tant2] - point.start[tant2] * point.end[tant1]) / (point.start[tant1] * point.end[tant1] + point.start[tant2] * point.end[tant2]);

      let quat = Cesium.Quaternion.fromAxisAngle(surface, Math.atan(tant)); // quat为围绕这个surface轴旋转d度的四元数
      let rot_mat3 = Cesium.Matrix3.fromQuaternion(quat);
      let m2 = Cesium.Matrix4.multiplyByMatrix3(modelMatrix, rot_mat3, new Cesium.Matrix4());
      Cesium.Matrix4.multiplyByUniformScale(modelMatrix, this.editModel.attribute.scale, modelMatrix);
      // 移动模型
      this.editModel.modelMatrix = m2;
      // 更新 坐标轴模型 
      this.updateAxisMatrix();
    };

    // 旋转和平移函数得到射线和面交点(基础方法)
    const axisTransForm = (modelMatrix, startCartesian3, endCartesian3, surface) => {
      var matrix = Cesium.Matrix4.inverseTransformation(modelMatrix, new Cesium.Matrix4());

      // 获取相机坐标
      var camera1 = this.viewer.camera.position;

      // 转 模型坐标
      var camera = Cesium.Matrix4.multiplyByPoint(matrix, camera1, new Cesium.Cartesian3());
      var startM = Cesium.Matrix4.multiplyByPoint(matrix, startCartesian3, new Cesium.Cartesian3());
      var endM = Cesium.Matrix4.multiplyByPoint(matrix, endCartesian3, new Cesium.Cartesian3());

      // 从相机看模型的方向
      var startDirection = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(startM, camera, new Cesium.Cartesian3()), new Cesium.Cartesian3());
      var endDirection = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(endM, camera, new Cesium.Cartesian3()), new Cesium.Cartesian3());

      // 面 
      var plane = Cesium.Plane.fromPointNormal(Cesium.Cartesian3.ZERO, surface);

      // 射线
      var startRay = new Cesium.Ray(camera, startDirection);
      var endRay = new Cesium.Ray(camera, endDirection);

      // 射线和面交点
      var start = Cesium.IntersectionTests.rayPlane(startRay, plane);
      var end = Cesium.IntersectionTests.rayPlane(endRay, plane);

      return { start: start, end: end };
    };
  }

  cameraControl(isCamera) {
    this.viewer.scene.screenSpaceCameraController.enableRotate = isCamera;
    this.viewer.scene.screenSpaceCameraController.enableTranslate = isCamera;
    this.viewer.scene.screenSpaceCameraController.enableZoom = isCamera;
    this.viewer.scene.screenSpaceCameraController.enableTilt = isCamera;
    this.viewer.scene.screenSpaceCameraController.enableLook = isCamera;
  }

  // 编辑模型位置
  updateByParams(options) {
    options.position = Cesium.Cartesian3.fromDegrees(options.lng, options.lat, options.height);
    let hpRoll = new Cesium.HeadingPitchRoll(Cesium.Math.toRadians(options.heading || 0), Cesium.Math.toRadians(options.pitch || 0), Cesium.Math.toRadians(options.roll || 0));
    let converter = Cesium.Transforms.eastNorthUpToFixedFrame;
    let modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(options.position, hpRoll, Cesium.Ellipsoid.WGS84, converter);
    if (options.scale) Cesium.Matrix4.multiplyByUniformScale(modelMatrix, options.scale, modelMatrix);
    this.editModel.modelMatrix = modelMatrix;
    this.editModel.attribute.scale = options.scale;
    this.updateAxisMatrix();
  }

  // 反向更新
  updateToView() {
    const modeInfo = this.getCurModelInfo();
    this.Vm.updateToView(modeInfo);
    console.log(modeInfo);
  }

  // 获取编辑模型信息
  getCurModelInfo() {
    let modelMatrix = this.editModel.modelMatrix;
    Cesium.Matrix4.multiplyByUniformScale(modelMatrix, 1 / this.editModel.attribute.scale, modelMatrix);
    let position = this.util.transformCartesianToWGS84(Cesium.Matrix4.getTranslation(modelMatrix, new Cesium.Cartesian3()));
    position.lng = position.lng.toFixed(6);
    position.lat = position.lat.toFixed(6);
    position.height = position.alt.toFixed(2);
    let result = { ...position };
    var m1 = Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Matrix4.getTranslation(modelMatrix, new Cesium.Cartesian3()), Cesium.Ellipsoid.WGS84, new Cesium.Matrix4(),);
    var m3 = Cesium.Matrix4.multiply(Cesium.Matrix4.inverse(m1, new Cesium.Matrix4()), modelMatrix, new Cesium.Matrix4());
    var mat3 = Cesium.Matrix4.getMatrix3(m3, new Cesium.Matrix3());
    var q = Cesium.Quaternion.fromRotationMatrix(mat3);
    var hpr = Cesium.HeadingPitchRoll.fromQuaternion(q);
    result.heading = Number(Cesium.Math.toDegrees(hpr.heading).toFixed(2));
    result.pitch = Number(Cesium.Math.toDegrees(hpr.pitch).toFixed(2));
    result.roll = Number(Cesium.Math.toDegrees(hpr.roll).toFixed(2));
    result.scale = this.editModel.attribute.scale || 1;
    Cesium.Matrix4.multiplyByUniformScale(modelMatrix, this.editModel.attribute.scale, modelMatrix);
    return result;
  }

  /**
   * 鼠标提示
   * */
  createTooltip() {
    let tooltip = document.createElement('DIV');
    document.body.appendChild(tooltip);
    tooltip.style = 'position: absolute;background: rgba(0,0,0,0.5); z-index: 999;line-height: 18px;pointer-events: none;';
    tooltip.innerHTML = `<span style="color: #fff; font-size: 12px;padding:4px" class="tooltip-text"></span>`;
    this.tooltip = tooltip;
  }

  // 事件开始
  m_start(text) {
    document.body.style.cursor = "crosshair";
    this.removeHandlersTooltip();
    this.showHideTooltip(true);
    setTimeout(() => {
      let tooltipText = this.tooltip.children[0];
      tooltipText && (tooltipText.innerText = text);
    }, 100);
  }

  // 事件结束
  m_end() {
    document.body.style.cursor = "default";
    this.removeHandlersTooltip();
    this.showHideTooltip(false);
  }

  m_destroy() {
    this.m_end();
    this.tooltip && this.tooltip.remove();
    this.tooltip = null;
  }

  showHideTooltip(state) {
    this.tooltip && (this.tooltip.style.display = state ? 'block' : 'none');
  }

  moveTooltip(movement) {
    this.tooltip.style.left = movement.endPosition.x + 320 + 'px';
    this.tooltip.style.top = movement.endPosition.y + 100 + 'px';
  }

  removeHandlersTooltip() {
    this.handlersTooltip && this.handlersTooltip.destroy();
    this.handlersTooltip = null;
  }

  destroy() {
    this.m_destroy();
    this.cancelEdit();
  }
}